//
//
//
//
//


#ifndef _LOGMANAGER_H_
#define _LOGMANAGER_H_

#include <strstream>
#include <iostream>
#include <fstream>
#include <vector>
#include "Mutex.h"
#include "datatypes.h"
#include "StrStream.h"

class BaseLogAdapter;
class LogManager
{
	public:
		enum ADAPTER_TYPE
		{
			UNKNOW_ADAPTER_TYPE 	= 0x00000000,
			FILE_ADAPTER_TYPE 		= 0x00000001,
			SYSLOG_ADAPTER_TYPE 	= 0x00000002,
			TCPCLIENT_ADAPTER_TYPE 	= 0x00000004,
			STDOUT_ADAPTER_TYPE 	= 0x00000008,
			SHMLOG_ADAPTER_TYPE 	= 0x00000010,
		};


		enum LOG_LEVEL
		{
			TRACE = 0x0000000000,
			INFO,
			DEBUG,
			WARNING,
			ERROR,
			CRITICAL,
		};


		typedef struct { LOG_LEVEL level; const char* info; }LOGLEVELINFO;

		static LOGLEVELINFO _LOG_LEVELS[6];

		static LogManager* Instance(void);
		static void Destroy(void);

		void Register(BaseLogAdapter* pAdapter);
		void UseAdapter(U32 adapterType);
		U32 UseAdapter(void);

		void LogLevel(LOG_LEVEL level);
		LOG_LEVEL LogLevel(void);

		void Log(LOG_LEVEL level, const std::string& info);
		void Flush(void);
		void Close(void);

		BaseLogAdapter* GetAdapter(ADAPTER_TYPE _type);

	protected:
		LogManager();
		~LogManager();

		std::string GetStrTime(const std::string& fmt);
		std::string Tid2Str(void);
	private:
		static LogManager* _instance;
		static Mutex _instanceMutex;

		std::vector<BaseLogAdapter*> _adapterVec;
		U32 _adapterType;
		LOG_LEVEL _level;

		Mutex	_writeMutex;
};


#define LOGTRACE(Message)  							\
{													\
	Util::StrStream str;							\
	str << Message;									\
	LogManager::Instance()->Log(LogManager::TRACE, str.AsString());	\
}

#define LOGTRACE2(Message1, Message2)				\
{													\
	Util::StrStream str;                            \
	str << Message1;								\
	str << Message2;								\
	LogManager::Instance()->Log(LogManager::TRACE, str.AsString());  \
}

#define LOGTRACE3(Message1, Message2, Message3) 	\
{													\
	Util::StrStream str;                            \
	str << Message1;                                \
	str << Message2;                                \
	str << Message3;                                \
	LogManager::Instance()->Log(LogManager::TRACE, str.AsString());  \
}

#define LOGTRACE4(Message1, Message2, Message3, Message4)	\
{															\
	Util::StrStream str;     								\
	str << Message1;     									\
	str << Message2;     									\
	str << Message3;     									\
	str << Message4;     									\
	LogManager::Instance()->Log(LogManager::TRACE, str.AsString());			\
}

//
//
// LOGINFO macro
#define LOGINFO(Message)							\
{													\
	Util::StrStream str;							\
	str << Message;									\
	LogManager::Instance()->Log(LogManager::INFO, str.AsString());  	\
}

#define LOGINFO2(Message1, Message2)				\
{													\
	Util::StrStream str;                            \
	str << Message1;                                \
	str << Message2;                                \
	LogManager::Instance()->Log(LogManager::INFO, str.AsString());   \
}

#define LOGINFO3(Message1, Message2, Message3)		\
{													\
	Util::StrStream str;                            \
	str << Message1;                                \
	str << Message2;                                \
	str << Message3;                                \
	LogManager::Instance()->Log(LogManager::INFO, str.AsString());   \
}

#define LOGINFO4(Message1, Message2, Message3, Message4)	\
{															\
	Util::StrStream str;                         			\
	str << Message1;                            			\
	str << Message2;                            			\
	str << Message3;                            			\
	str << Message4;                            			\
	LogManager::Instance()->Log(LogManager::INFO, str.AsString());   		\
}


//
//
// LOGDEBUG macros
#define LOGDEBUG(Message)							\
{													\
	Util::StrStream str;                            \
	str << Message;                                 \
	LogManager::Instance()->Log(LogManager::DEBUG,  str.AsString());	\  
}

#define LOGDEBUG2(Message1, Message2)				\
{													\
	Util::StrStream str;                            \
	str << Message1;                                \
	str << Message2;                                \
	LogManager::Instance()->Log(LogManager::DEBUG,  str.AsString()); \
}

#define LOGDEBUG3(Message1, Message2, Message3)		\
{													\
	Util::StrStream str;                            \
	str << Message1;                                \
	str << Message2;                                \
	str << Message3;                                \
	LogManager::Instance()->Log(LogManager::DEBUG,  str.AsString()); \
}


#define LOGDEBUG4(Message1, Message2, Message3, Message4)	\
{															\
	Util::StrStream str;                            		\
	str << Message1;                                		\
	str << Message2;                                		\
	str << Message3;                                		\
	str << Message4;                                		\
	LogManager::Instance()->Log(LogManager::DEBUG,  str.AsString()); 		\
}

#define LOGWARN(Message)							\
{													\
	Util::StrStream str;                            \
	str << Message;                                 \
	LogManager::Instance()->Log(LogManager::WARNING, str.AsString());\
}

#define LOGWARN2(Message1, Message2)				\
{													\
	Util::StrStream str;                            \
	str << Message1;                                \
	str << Message2;                                \
	LogManager::Instance()->Log(LogManager::WARNING, str.AsString());\
}


#define LOGWARN3(Message1, Message2, Message3)		\
{													\
	Util::StrStream str;                            \
	str << Message1;                                \
	str << Message2;                                \
	str << Message3;                                \
	LogManager::Instance()->Log(LogManager::WARNING, str.AsString());\
}

#define LOGWARN4(Message1, Message2, Message3, Message4)	\
{															\
	Util::StrStream str;									\
	str << Message1;										\
	str << Message2;										\
	str << Message3;										\
	str << Message4;										\
	LogManager::Instance()->Log(LogManager::WARNING, str.AsString());\
}

//
// LOGERROR macros
#define LOGERROR(Message)							\
{													\
	Util::StrStream str;                            \
	str << Message;                                 \
	LogManager::Instance()->Log(LogManager::ERROR,  str.AsString()); \
}

#define LOGERROR2(Message1, Message2)				\
{													\
	Util::StrStream str;							\
	str << Message1;								\
	str << Message2;								\
	LogManager::Instance()->Log(LogManager::ERROR,  str.AsString()); \
}

#define LOGERROR3(Message1, Message2, Message3)		\
{													\
	Util::StrStream str;                            \
	str << Message1;                                \
	str << Message2;                                \
	str << Message3;                                \
	LogManager::Instance()->Log(LogManager::ERROR,  str.AsString()); \
}

#define LOGERROR4(Message1, Message2, Message3, Message4)	\
{															\
	Util::StrStream str;									\
	str << Message1;                                		\
	str << Message2;                                		\
	str << Message3;                                		\
	str << Message4;                                		\
	LogManager::Instance()->Log(LogManager::ERROR,  str.AsString()); 		\
}
#endif // _LOGMANAGER_H_
